﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Mbs.Utils.ThreadPool
{
    /// <summary>
    /// 包装的任务类
    /// </summary>
    public class WorkTask
    {
        public static WorkTaskFactory Factory { get; private set; } = new WorkTaskFactory();
        /// <summary>
        /// 任务运行结束时触发该事件
        /// </summary>
        public event Action<WorkTask>? TaskCompleted;
        /// <summary>
        /// 任务ID
        /// </summary>
        private static int _id = 0;
        /// <summary>
        /// 委托给任务不带执行参数的代码
        /// </summary>
        private readonly Action? action;
        /// <summary>
        /// 委托给任务执行的带输入参数代码
        /// </summary>
        private readonly Action<object?>? actionWithParamter;
        /// <summary>
        /// 线程间的同步事件
        /// </summary>
        public AutoResetEvent WaitHandle { get; protected set; } = new AutoResetEvent(false);
        /// <summary>
        /// 执行代码的参数
        /// </summary>
        public object? State { get; protected set; }
        /// <summary>
        /// 接收任务抛出的异常
        /// </summary>
        public WorkTaskException? Exception { get; protected set; }
        /// <summary>
        /// 任务是否完成标志
        /// </summary>
        public bool IsCompleted { get; protected set; } = false;
        /// <summary>
        /// 任务知否有异常
        /// </summary>
        public bool IsFaulted { get; protected set; } = false;
        /// <summary>
        /// 任务状态
        /// </summary>
        public WorkTaskStatus Status { get; protected set; } = WorkTaskStatus.Created;
        public int Id { get { return Interlocked.Increment(ref _id); } }
        protected WorkTask() { }

        protected void OnTaskCompleted(WorkTask sender)
        {
            TaskCompleted?.Invoke(sender);
        }
        public WorkTask(Action action)
        {
            this.action = action ?? throw new ArgumentNullException(nameof(action));
        }
        public WorkTask(Action<object?> action, object state)
        {
            actionWithParamter = action ?? throw new ArgumentNullException(nameof(action));
            this.State = state;
        }
        /// <summary>
        /// 任务的同步方法
        /// </summary>
        public virtual void Runsynchronous()
        {
            if (Status != WorkTaskStatus.Created) return;
            Status = WorkTaskStatus.Running;
            try
            {
                action?.Invoke();
                actionWithParamter?.Invoke(State);
            }
            catch (Exception ex)
            {
                Exception = new WorkTaskException(ex.Message, ex);
                IsFaulted = true;
            }
            finally
            {
                OnTaskCompleted(this);
                WaitHandle.Set();
                IsCompleted = true;
                Status = WorkTaskStatus.RanToCompleted;
            }
        }
        /// <summary>
        /// 通过调用线程执行的方法
        /// </summary>
        public void Start()
        {
            Factory.ThreadPoolExcutor?.QueueTask(this);
        }
        /// <summary>
        /// 取消【在放入队列前，使用StartNew时无效】
        /// 仅能取消在放入队列前未开始执行的任务
        /// 已经开始执行的任务，需要在任务体内完成中止
        /// 
        /// </summary>
        public void Cancle()
        {
            if (Status != WorkTaskStatus.Created)
            {
                Status = WorkTaskStatus.Canceled;
            }
        }

        /// <summary>
        /// 通过调用线程执行的方法
        /// </summary>
        /// <param name="executor">线程池管理类</param>
        public void Start(ThreadPoolExecutor executor)
        {
            executor.QueueTask(this);
        }
        /// <summary>
        /// 执行一组任务并等待所有任务完成。
        /// </summary>
        /// <param name="tasks">一组任务</param>
        /// <returns>所有任务是否都接收到完成的信号。</returns>
        public static bool WaitAll(WorkTask[] tasks)
        {
            var result = true;
            foreach (var task in tasks)
            {
                result = result && task.WaitHandle.WaitOne();
            }
            return result;
        }

        /// <summary>
        /// 执行一组任务并等待任意一个任务完成。
        /// </summary>
        /// <param name="tasks">一组任务</param>
        /// <returns>返回已完成任务的索引</returns>
        public static int WaitAny(WorkTask[] tasks)
        {
            var index = new Random().Next(0, tasks.Length - 1);
            tasks[index].WaitHandle.WaitOne();
            return index;
        }
    }
    /// <summary>
    /// 具有返回类型的任务
    /// </summary>
    /// <typeparam name="TResult"></typeparam>
    public class WorkTask<TResult> : WorkTask
    {
        private readonly Func<TResult>? func;
        private readonly Func<object?, TResult>? funcWithParameter;

        protected TResult? _result = default(TResult);
        public TResult? Result { get; private set; }
        public WorkTask(Func<TResult> func)
        {
            this.func = func ?? throw new ArgumentNullException(nameof(func));
        }
        /// <summary>
        /// 函数体
        /// </summary>
        /// <param name="func">函数</param>
        /// <param name="state">参数</param>
        /// <exception cref="ArgumentNullException"></exception>
        public WorkTask(Func<object?, TResult> func, object? state)
        {
            this.funcWithParameter = func ?? throw new ArgumentNullException(nameof(func));
            this.State = state;
        }

        public override void Runsynchronous()
        {
            if (Status != WorkTaskStatus.Created) return;
            Status = WorkTaskStatus.Running;
            try
            {
                if (func != null) Result = func();
                if (funcWithParameter != null) Result = funcWithParameter(State);
            }
            catch (Exception ex)
            {
                Exception = new WorkTaskException(ex.Message, ex);
                IsFaulted = true;
            }
            finally
            {
                OnTaskCompleted(this);
                WaitHandle.Set();
                Status = WorkTaskStatus.RanToCompleted;
                IsCompleted = true;

            }
        }
    }
    public class WorkTaskException : Exception
    {
        public WorkTaskException()
        {
        }
        public WorkTaskException(string Message)
            : base(Message)
        {
        }

        public WorkTaskException(string Message, Exception InnerException)
            : base(Message, InnerException)
        {
        }
    }

    public enum WorkTaskStatus
    {
        /// <summary>
        /// 已创建
        /// </summary>
        Created = 0,
        /// <summary>
        /// 正在运行
        /// </summary>
        Running = 1,
        /// <summary>
        /// 已完成
        /// </summary>
        RanToCompleted = 2,
        /// <summary>
        /// 取消
        /// </summary>
        Canceled = 3,
    }
}